home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 08 - 1992 / 08.03 Jul 92 / BigNums / bignums-object.sch < prev    next >
Encoding:
Text File  |  1990-06-03  |  7.7 KB  |  222 lines  |  [TEXT/EDIT]

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ; File:  bignums-object.sch ;
  3. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  4. ;
  5. (define make-bignum-object
  6.   (lambda (internal-bignum . bases)
  7.     (make-bignum-result-object
  8.      (trampoline make-bignum
  9.                  (cons internal-bignum
  10.                        bases))
  11.      (to-base?? bases))))
  12. ;
  13. (define make-bignum-result-object
  14.   (lambda (user-bignum base)
  15.     (let ((type 'soft-bignum)
  16.           (the-remainder #f))
  17.       (lambda (message . args)
  18.         (cond ((eq? message 'get-base)
  19.                base)
  20.               ((eq? message 'change-base)
  21.                (begin
  22.                 (if 
  23.                  (or (bignum-zero? user-bignum)
  24.                      (bignum-=? user-bignum 
  25.                                 bignum-one))
  26.                  (set! base 'all)
  27.                  (begin 
  28.                   (set! user-bignum
  29.                         (bignum-base-n->bignum-base-m 
  30.                          user-bignum
  31.                          base
  32.                          (car args)))
  33.                   (set! base (car args))))
  34.                 base))
  35.               ((eq? message 'change-sign)
  36.                (begin 
  37.                 (set! user-bignum 
  38.                       (bignum-change-sign
  39.                        user-bignum))
  40.                 user-bignum))
  41.               ((eq? message 'get-type)
  42.                type)
  43.               ((eq? message 'get-number)
  44.                user-bignum)
  45.               ((eq? message 'show-number)
  46.                (show-bignum user-bignum))
  47.               ((eq? message 'get-remainder)
  48.                the-remainder)
  49.               ((eq? message 'show-remainder)
  50.                (show-bignum the-remainder))
  51.               ((eq? message 'set-remainder)
  52.                (set! the-remainder (car args)))
  53.               ((eq? message '?)
  54.                '(get-base change-base change-sign 
  55.                  get-type get-number show-number 
  56.                  get-remainder show-remainder
  57.                  set-remainder ?))
  58.               (else
  59.                (error "Bad message to bignum object." 
  60.                       message)))))))
  61. ;
  62. (define copy-bignum-object
  63.   (lambda (object)
  64.     (let ((result (make-bignum-result-object 
  65.                    (object 'get-number) 
  66.                    (object 'get-base))))
  67.       (begin
  68.        (result 'set-remainder (object 'get-remainder))
  69.        result))))
  70. ;
  71. ; Note:  Friends and associates of bignum-=? are left 
  72. ; to the reader to implement.  They all will look quite
  73. ; similar to the below.
  74. ;
  75. (define bignum-=?
  76.   (lambda (first second)
  77.     (let ((first-sign (get-sign first))
  78.           (second-sign (get-sign second)))
  79.       (if (and (eq? first-sign second-sign)
  80.                (big-=? (bignum-abs first)
  81.                        (bignum-abs second)))
  82.           #t
  83.           #f))))
  84. (define make-objects-base-compatible
  85.   (lambda (object1 object2)
  86.     (let ((object1-base (object1 'get-base))
  87.           (object2-base (object2 'get-base)))
  88.       (if (or (eq? object1-base 'all)
  89.               (eq? object2-base 'all)
  90.               (=? object1-base object2-base))
  91.           (cons object1 object2)
  92.           (if (>? object1-base 
  93.                   object2-base)
  94.               (cons object1
  95.                     (let ((second-object 
  96.                            (copy-bignum-object 
  97.                             object2)))
  98.                       (second-object 'change-base 
  99.                                      object1-base)
  100.                       second-object))
  101.               (cons (let ((first-object 
  102.                            (copy-bignum-object 
  103.                             object1)))
  104.                       (first-object 'change-base 
  105.                                     object2-base)
  106.                       first-object)
  107.                     object2))))))
  108. ;
  109. (define find-common-base
  110.   (lambda (object1 object2)
  111.     (let ((object1-base (object1 'get-base))
  112.           (object2-base (object2 'get-base)))
  113.       (if (eq? object1-base 'all)
  114.           (if (eq? object2-base 'all)
  115.               10
  116.               object2-base)
  117.           (if (eq? object2-base 'all)
  118.               object1-base
  119.               (if (>? object1-base object2-base)
  120.                   object1-base
  121.                   object2-base))))))
  122. ;       
  123. (define bignum-object-div
  124.   (lambda (dividend divisor)
  125.     (let ((pair-of-objects (make-objects-base-compatible 
  126.                             dividend divisor)))
  127.       (let ((dividend (car pair-of-objects))
  128.             (divisor (cdr pair-of-objects)))
  129.         (let 
  130.           ((base (find-common-base dividend divisor)))
  131.           (let 
  132.             ((result (bignum-div (dividend 'get-number)
  133.                                  (divisor 'get-number)
  134.                                  base)))
  135.             (let ((the-quotient (first-digit result))
  136.                   (the-remainder (rest-digits result)))
  137.               (let ((return-value 
  138.                      (make-bignum-result-object 
  139.                       the-quotient base)))
  140.                 (begin (return-value 'set-remainder 
  141.                                      the-remainder)
  142.                        return-value)))))))))
  143. ;
  144. (define bignum-object-mul
  145.   (lambda (multiplicand multiplier)
  146.     (let ((pair-of-objects 
  147.            (make-objects-base-compatible multiplicand 
  148.                                          multiplier)))
  149.       (let ((multiplicand (car pair-of-objects))
  150.             (multiplier (cdr pair-of-objects)))
  151.         (let ((base (find-common-base multiplicand 
  152.                                       multiplier)))
  153.           (let ((result (bignum-mul (multiplicand 
  154.                                      'get-number)
  155.                                     (multiplier 
  156.                                      'get-number)
  157.                                     base)))
  158.             (make-bignum-result-object result 
  159.                                        base)))))))
  160. ;
  161. (define bignum-object-add
  162.   (lambda (addend augend)
  163.     (let ((pair-of-objects 
  164.            (make-objects-base-compatible addend 
  165.                                          augend)))
  166.       (let ((addend (car pair-of-objects))
  167.             (augend (cdr pair-of-objects)))
  168.         (let ((base (find-common-base addend augend)))
  169.           (let ((result (bignum-add 
  170.                          (addend 'get-number)
  171.                          (augend 'get-number)
  172.                          base)))
  173.             (make-bignum-result-object result 
  174.                                        base)))))))
  175. ;   
  176. (define bignum-object-sub
  177.   (lambda (minuend subtrahend)
  178.     (let ((pair-of-objects (make-objects-base-compatible 
  179.                             minuend subtrahend)))
  180.       (let ((minuend (car pair-of-objects))
  181.             (subtrahend (cdr pair-of-objects)))
  182.         (let ((base (find-common-base minuend 
  183.                                       subtrahend)))
  184.           (let ((result 
  185.                  (bignum-sub (minuend 'get-number)
  186.                              (subtrahend 'get-number)
  187.                              base)))
  188.             (make-bignum-result-object result 
  189.                                        base)))))))
  190. ;
  191. ; The below could be put into bignum object definition.
  192. ;
  193. (define bignum-object-base-n->bignum-object-base-m
  194.   (lambda (bignum-object from-base to-base)
  195.     (let ((result (bignum-base-n->bignum-base-m 
  196.                    (bignum-object 'get-number)
  197.                    from-base
  198.                    to-base)))
  199.       (make-bignum-result-object result to-base))))
  200. ;
  201. (define bignum-object-zero?
  202.   (lambda (candidate)
  203.     (bignum-zero? (candidate 'get-number))))
  204. ;
  205. (define bignum-object-zero
  206.   (make-bignum-object ()))
  207. ;
  208. (define bignum-object-one
  209.   (make-bignum-object '(1)))
  210. ;
  211. (define bignum-object-fact
  212.   (lambda (n)
  213.     (if (bignum-object-zero? n)
  214.         bignum-object-one
  215.         (bignum-object-mul 
  216.          n
  217.          (bignum-object-fact 
  218.           (bignum-object-sub n 
  219.                              bignum-object-one))))))
  220. ;             
  221. 'done